package com.bangcommunity.bbframe.common.exception;

import com.bangcommunity.bbframe.common.base.BaseResult;
import com.bangcommunity.bbframe.common.base.ResultCode;
import com.bangcommunity.bbframe.common.utils.lang.StringUtils;
import com.bangcommunity.bbframe.common.utils.reflect.ClassUtils;

import java.io.IOException;
import java.io.InterruptedIOException;
import java.io.LineNumberReader;
import java.io.PrintWriter;
import java.io.StringReader;
import java.io.StringWriter;
import java.lang.reflect.Method;
import java.util.ArrayList;

/**
 * @author huaicheng.thc Date: 2015-11-05 17:18:04
 */
public class ExceptionUtil {

    public static boolean hasBaseRtmException(Method method) {
        return hasException(method, BaseRtmException.class);
    }

    public static boolean hasException(Method method, Class<?> e) {
        Class<?>[] exceptionTypes = method.getExceptionTypes();
        if (null != exceptionTypes) {
            for (Class<?> c : exceptionTypes) {
                if (e.equals(c)) {
                    return true;
                }
            }
        }
        return false;
    }

    public static BaseResult baseCustomeRtmExceptionToBaseResult(BaseRtmException excep) {
        if (null != excep) {
            String message = excep.getMessage();
            return BaseResult.fail(StringUtils.isNotBlank(message) ? message : "服务调用错误");
        }
        return null;
    }

    public static BaseException convertRtmExceptionToExeption(BaseRtmException throwable) {
        if (null == throwable) {
            return null;
        }
        return new BaseException(
                throwable.getErrorCode() == null ? ResultCode.OTHER.getCode() : throwable.getErrorCode(),
                throwable.getMessage());
    }

    public static Throwable getCause(Throwable throwable, Class... skipClasss) {
        if (null == throwable) {
            return null;
        }
        if (null == skipClasss) {
            return throwable.getCause();
        }
        boolean isAssign = false;
        for (Class t : skipClasss) {
            isAssign = ClassUtils.isAssignable(t, throwable.getClass());
            if (isAssign) {
                break;
            }
        }
        if (isAssign) {
            Throwable cause = throwable.getCause();
            if (null == cause) {
                return null;
            }
            return getCause(cause);
        }
        return throwable;
    }

    /**
     * Render throwable using Throwable.printStackTrace.
     * 
     * @param throwable
     *            throwable, may not be null.
     * @return string representation.
     */
    public static String[] render(final Throwable throwable) {
        StringWriter sw = new StringWriter();
        PrintWriter pw = new PrintWriter(sw);
        try {
            throwable.printStackTrace(pw);
        } catch (RuntimeException ex) {
        }
        pw.flush();
        LineNumberReader reader = new LineNumberReader(new StringReader(sw.toString()));
        ArrayList lines = new ArrayList();
        try {
            String line = reader.readLine();
            while (line != null) {
                lines.add(line);
                line = reader.readLine();
            }
        } catch (IOException ex) {
            if (ex instanceof InterruptedIOException) {
                Thread.currentThread().interrupt();
            }
            lines.add(ex.toString());
        }
        String[] tempRep = new String[lines.size()];
        lines.toArray(tempRep);
        return tempRep;
    }

    /**
     */
    public static String renderToExceptionString(final Throwable throwable) {
        return renderToExceptionString(throwable,false);
    }
    /**
     */
    public static String renderToExceptionString(final Throwable throwable,boolean replaceCR) {
        StringWriter sw = new StringWriter();
        PrintWriter pw = new PrintWriter(sw);
        try {
            throwable.printStackTrace(pw);
        } catch (RuntimeException ex) {
        }
        pw.flush();
        String exceptionString = sw.toString();
        if(replaceCR){
            return exceptionString.replaceAll("\n","#_#").replaceAll("\t","");
        }
        return exceptionString;
    }

    public static void main(String[] args) {
        BaseRtmException baseRtmException1 = new BaseRtmException("abc1");
        BaseRtmException baseRtmException2 = new BaseRtmException("abc2", baseRtmException1);
        BaseRtmException baseRtmException3 = new BaseRtmException("abc3", baseRtmException2);
        System.out.println(renderToExceptionString(baseRtmException3));
        System.out.println(renderToExceptionString(baseRtmException3,true));
        System.out.println(renderToExceptionString(baseRtmException3).length());

    }
}
